#! /bin/sh
# Autodetection script for scanning /sys for hardware
# for Archlinux by Tobias Powalowski <tpowa@archlinux.org>
usage () {
	echo "$0 [options]"
	echo ""
	echo " This is a tool that detects/lists modules that are exported by /sys"
	echo ""
	echo "  Options:"
	echo "    --kernel_version=      use kernel version (no autodetect)"
	echo "    --kernel_directory=    use kernel module directory (no autodetect)"
	echo "    --show-modules         show all detected modules"
	echo "    --show-modules-order   shows load order of detected modules"
	echo "    --show-agp             show AGP modules"
	echo "    --show-acpi            show ACPI modules"
        echo "    --show-block           show BLOCK DEVICE modules"
        echo "    --show-bluetooth       show BLUETOOTH modules"
        echo "    --show-cdrom           show CDROM modules"
        echo "    --show-cpufreq         show CPUFREQ modules"
        echo "    --show-crypto          show CRYPTO modules"
        echo "    --show-drm             show DRM modules"
        echo "    --show-hwmon           show HWMON modules"
        echo "    --show-i2c             show I2C modules"
	echo "    --show-input           show INPUT modules"
	echo "    --show-irda            show IRDA modules"
	echo "    --show-isdn            show ISDN modules"
        echo "    --show-kvm             show KVM modules"
        echo "    --show-media           show MEDIA modules"
	echo "    --show-net             show NETWORK modules"
	echo "    --show-parport         show PARPORT modules"
	echo "    --show-pcmcia          show PCMCIA modules"    
	echo "    --show-sound           show SOUND modules"
	echo "    --show-staging         show STAGING modules"
        echo "    --show-tpm             show TPM modules"
        echo "    --show-watchdog        show WATCHDOG modules"
	echo "    --show-other           show OTHER modules"
	echo ""
	echo "  For /etc/mkinitcpio.conf use:"
	echo "    --filesystem           add filesystems to MODULES="
	echo "    --hostcontroller       show MODULES= for all hostcontrollers"
	echo "    --ati-kms              add ati kernel mode setting" 
	echo "    --intel-kms            add intel kernel mode setting"
	echo "    --nvidia-kms           add nvidia kernel mode setting"
        echo "" 
	echo "    --rootdevice=          autodetected advanced features of rootdevice"
	echo "    --hooks-dir=           use this directory for HOOKS check"
	echo "    --advanced             show autodetected advanced HOOKS"
	echo "    --hooks                show HOOKS="
	echo "    --dmraid               add dmraid to HOOKS="
	echo "    --keymap               add keymap to HOOKS="
	echo "    --pcmcia               add pcmcia to HOOKS="
	echo "    --nfs                  add net to HOOKS="
	exit 1
}

[ "$1" = "" ]       && usage
[ "$1" = "--help" ] && usage
[ "$1" = "-h" ]     && usage

# setting parameters
PARAMETER="$(echo $*)"
parameter() {
	while [ -n "$1" ]; do
		case $1 in
			--kernel_directory=*)
			KERNEL_DIRECTORY="$(echo $1 | awk -F= '{print $2;}')"
			;;
			--kernel_version=*)
			KERNEL_VERSION="$(echo $1 | awk -F= '{print $2;}')"
			;;
			--rootdevice=*)
			ROOTDEVICE="$(echo $1 | awk -F= '{print $2;}')"
			;;
			-hooks-dir=*|--hooks-dir=*)
			HOOKS_DIR="$(echo $1 | awk -F= '{print $2;}')"
			;;
		esac
		shift
	done
}

parameter $PARAMETER

if [ "$KERNEL_VERSION" = "" ]; then
	KERNEL_VERSION="$(uname -r)"
fi

# dmraid switch
[ "$(echo $* | grep '\-dmraid')" ] && DMRAID=1

# keymap switch
[ "$(echo $* | grep '\-keymap')" ] && KEYMAP=1

# pcmcia switch
[ "$(echo $* | grep '\-pcmcia')" ] && PCMCIA=1

# nfs switch
[ "$(echo $* | grep '\-nfs')" ] && NFS=1

# hooks switch
[ "$(echo $* | grep '\-hooks')" ] && HOOKS=1

ADVANCED=""
# root device check
if ! [ "$ROOTDEVICE" = "" ]; then
	ADVANCED="$(echo $(echo "$(lsblk -rpsno TYPE $ROOTDEVICE | grep -ve "disk" -e "part")" | tac) | sed -e 's#crypt#encrypt#g' -e 's#raid.*[0-9]#mdadm_udev#g' -e 's#lvm#lvm2#g')"
fi

: >/tmp/modules-plain
: >/tmp/modules-stripped
: >/tmp/.blkid

# generate blkid
blkid -c /dev/null -s TYPE > /tmp/.blkid

# find modaliases
aliases=$(find /sys/ -noleaf -name modalias  -exec cat {} +)

# generate files for the different actions
modprobe -i -a --dirname=$KERNEL_DIRECTORY --set-version=$KERNEL_VERSION --show-depends $aliases >> /tmp/modules-plain 2>/dev/null
sort -u /tmp/modules-plain >> /tmp/modules-stripped

listmods() {
	key=$1 ; shift
	ex=
	while [ "$1" ]; do
		[ "$ex" ] && ex="$ex|$1" || ex="$1"
		shift
	done
	for ln in $(grep "$key" /tmp/modules-stripped | sed 's|^insmod ||g'); do
		if [ "$ex" ]; then
			echo $ln | egrep -v "$ex" | sed -ne "s#^/.*/\(.*\)\.ko.*#\1#p"
		else
			echo $ln | sed -ne "s#^/.*/\(.*\)\.ko.*#\1#p"
		fi
	done
}
showlist() {
	cat=$1 ; shift
	[ $# -gt 0 ] || return
	echo -n "$cat: "
	for i in $*; do echo -n "$i "; done
	echo ""
}

showlist2() {
	cat=$1 ; shift
	[ $# -gt 0 ] || return
	echo -n "$cat="
	for i in $*; do echo -n "$i "; done
	echo ""
}

# starting different actions
while [ -n "$*"  ]; do
	case $1 in
		--show-modules)
			showlist "AGP      " $(listmods agp/)
			showlist "ACPI     " $(listmods acpi/)
			showlist "BLOCK    " $(listmods ata/pata pata_acpi) $(listmods ata/ata_piix) \
					     $(listmods virtio/virtio_pci) $(listmods scsi/) $(listmods message/fusion/) $(listmods drivers/block/ nbd pktcdvd sx8 floppy) \
					     $(listmods ata/ pata ata_generic) $(listmods drivers/block/sx8) \
					     $(listmods usb/ usb/input) $(listmods firewire/) $(listmods ieee1394/) $(listmods nvme/)
			showlist "BLUETOOTH" $(listmods bluetooth/)
			showlist "CDROM    " $(listmods cdrom/)
			showlist "CPUFREQ  " $(listmods cpufreq/)
			showlist "CRYPTO   " $(listmods crypto/)
			showlist "DRM      " $(listmods drm/)
			showlist "HWMON    " $(listmods hwmon/)
			showlist "I2C      " $(listmods i2c/)
			showlist "INPUT    " $(listmods input/ pcspkr) $(listmods hid/)
			showlist "IRDA     " $(listmods irda/)
			showlist "ISDN     " $(listmods isdn/)
			showlist "KVM      " $(listmods kvm/)
			showlist "MEDIA    " $(listmods media/)
			showlist "NET      " $(listmods net/ irda/)
			showlist "PARPORT  " $(listmods parport/)
			showlist "PCMCIA   " $(listmods pcmcia/)
			showlist "SOUND    " $(listmods pcspkr) $(listmods sound/)
			showlist "STAGING  " $(listmods staging/)
			showlist "TPM      " $(listmods tpm/)
			showlist "WATCHDOG " $(listmods watchdog/)
			showlist "OTHER    " $(listmods modules/ agp/ acpi/ scsi/ message/fusion block/sx8 block/cciss block/cpqarray block/DAC960 block/virtio virtio/virtio_pci ata/ \
						usb/ ieee1394 bluetooth/ cdrom/ cpufreq/ crypto/ net/ hwmon/ i2c/ isdn/ input/ irda/ kvm/ media/ parport/ pcmcia/ sound/ tpm/ drm/ firewire/ hid/ staging/ watchdog/)
			;;

		--show-modules-order)
			showlist "MODULES ORDER" $(listmods modules/)
			;;

		--show-agp)       showlist "AGP      " $(listmods agp/) ;;
		--show-acpi)      showlist "ACPI     " $(listmods acpi/) ;;
		--show-block)     showlist "BLOCK    " $(listmods ata/pata pata_acpi) $(listmods ata/ata_piix) \
						       $(listmods virtio/virtio_pci) $(listmods scsi/) $(listmods message/fusion/) $(listmods drivers/block/ nbd pktcdvd sx8 floppy) \
						       $(listmods ata/ pata ata_generic) $(listmods drivers/block/sx8) \
						       $(listmods usb/ usb/input) $(listmods firewire/) $(listmods ieee1394/) $(listmods nvme/) ;;
		--show-bluetooth) showlist "BLUETOOTH" $(listmods bluetooth/) ;;
		--show-cdrom)     showlist "CDROM    " $(listmods cdrom/) ;;
		--show-cpufreq)   showlist "CPUFREQ  " $(listmods cpufreq/) ;;
		--show-crypto)    showlist "CRYPTO   " $(listmods crypto/) ;;
		--show-drm)       showlist "DRM      " $(listmods drm/) ;;
		--show-hwmon)     showlist "HWMON    " $(listmods hwmon/) ;;
		--show-input)     showlist "INPUT    " $(listmods input/ pcspkr) $(listmods hid/) ;;
		--show-i2c)       showlist "I2C      " $(listmods i2c/) ;;
		--show-irda)      showlist "IRDA     " $(listmods irda/) ;;
		--show-isdn)      showlist "ISDN     " $(listmods isdn/) ;;
		--show-kvm)       showlist "KVM      " $(listmods kvm/) ;;
		--show-media)     showlist "MEDIA    " $(listmods media/) ;;
		--show-net)       showlist "NET      " $(listmods net/ irda/) ;;
		--show-parport)   showlist "PARPORT  " $(listmods parport/) ;;
		--show-pcmcia)    showlist "PCMCIA   " $(listmods pcmcia/) ;;
		--show-sound)     showlist "SOUND    " $(listmods pcspkr) $(listmods sound/) ;;
		--show-staging)   showlist "STAGING  " $(listmods staging/) ;;
		--show-tpm)       showlist "TPM      " $(listmods tpm/) ;;
		--show-watchdog)  showlist "WATCHDOG " $(listmods watchdog/) ;;
		--show-other)     showlist "OTHER    " $(listmods .ko agp/ acpi/ scsi/ message/fusion block/sx8 block/cciss block/cpqarray block/DAC960 block/virtio virtio/virtio_pci ata/ \
							usb/ ieee1394 bluetooth/ cpufreq/ crypto/ net/ hwmon/ i2c/ isdn/ input/ irda/ kvm/ media/ parport/ pcmcia/ sound/ tpm/ drm/ firewire/ hid/ staging/ watchdog/) ;;
		--filesystem)   FILESYSTEM="ext2 ext3 ext4 f2fs nilfs2 btrfs reiserfs xfs jfs vfat"
				for i in $FILESYSTEM; do
					 [ "$(grep $i /tmp/.blkid)" ] && FS="$FS $i"
				done
				[ "$(echo $FS | grep btrfs)" ] && FS="$FS crc32c"
				MODULES_INITRAMFS="$MODULES_INITRAMFS $FS"
				showlist2 "MODULES" \"$MODULES_INITRAMFS\" | sed -e 's/(\  /(/g' -e 's/"\ /"/g' -e 's/\ "/"/g' -e 's/\ \ /\ /g'
				;;
		--hostcontroller)HOSTCONTROLLER="$(listmods virtio/virtio_pci) $(listmods ata/pata pata_acpi) $(listmods scsi/ /sg.ko /st.ko scsi_mod sr_mod sd_mod) $(listmods message/fusion/) $(listmods drivers/block/ virtio_blk nbd pktcdvd sx8 floppy) $(listmods ata/ pata ata_generic) $(listmods drivers/block/sx8) $(listmods xhci-hcd) $(listmods ehci-hcd) $(listmods uhci-hcd) $(listmods ohci-hcd) $(listmods virtio_blk) $(listmods nvme/)" 
				 MODULES_INITRAMFS="$MODULES_INITRAMFS $HOSTCONTROLLER"
				 showlist2 "MODULES" \"$MODULES_INITRAMFS\" | sed -e 's/(\  /(/g' -e 's/"\ /"/g' -e 's/\ "/"/g' -e 's/\ \ /\ /g'
				 ;;
		--ati-kms) 	KMS="radeon"
				MODULES_INITRAMFS="$KMS $MODULES_INITRAMFS"
				showlist2 "MODULES" \"$MODULES_INITRAMFS\" | sed -e 's/(\  /(/g' -e 's/"\ /"/g' -e 's/\ "/"/g' -e 's/\ \ /\ /g'
				;;
		--intel-kms) 	KMS="i915"
				MODULES_INITRAMFS="$KMS $MODULES_INITRAMFS"
				showlist2 "MODULES" \"$MODULES_INITRAMFS\" | sed -e 's/(\  /(/g' -e 's/"\ /"/g' -e 's/\ "/"/g' -e 's/\ \ /\ /g'
				;;
		--nvidia-kms) 	KMS="nouveau"
				MODULES_INITRAMFS="$KMS $MODULES_INITRAMFS"
				showlist2 "MODULES" \"$MODULES_INITRAMFS\" | sed -e 's/(\  /(/g' -e 's/"\ /"/g' -e 's/\ "/"/g' -e 's/\ \ /\ /g'
				;;
		--hooks) 
			if [ "$HOOKS_DIR" = "" ]; then
				HOOKS_DIR="/usr/lib/initcpio/install"
			fi
			START_HOOKS="base udev keymap autodetect modconf block pcmcia net dmraid keyboard $ADVANCED filesystems fsck"
			# remove the ones that don't exist on the system
			for i in ${START_HOOKS}; do
				if ! [ -e "${HOOKS_DIR}/$i" ]; then 
					START_HOOKS=$(echo $START_HOOKS | sed -e "s/${i}\ //g")
				fi
			done
			if ! [ "$KEYMAP" = "1" ]; then 
				START_HOOKS=$(echo $START_HOOKS | sed -e "s/keymap//g")
			fi
			if ! [ "$DMRAID" = "1" ]; then 
				START_HOOKS=$(echo $START_HOOKS | sed -e "s/dmraid//g")
			fi
			if ! [ "$PCMCIA" = "1" ]; then
				START_HOOKS=$(echo $START_HOOKS | sed -e "s/pcmcia//g")
			fi
			if ! [ "$NFS" = "1" ]; then
				START_HOOKS=$(echo $START_HOOKS | sed -e "s/net//g")
			fi
			echo "HOOKS=\"$START_HOOKS\"" | sed -e 's/"\ /"/g' -e 's/\ "/"/g' -e 's/\ \ /\ /g'
		;;
		--advanced) echo "$ADVANCED"
			    ;;
	esac
	shift
done

# cleanup
rm /tmp/modules-plain
rm /tmp/modules-stripped
rm /tmp/.blkid

# vim: set ts=2 sw=2 noet:
